import { Inject, Provide } from '@midwayjs/decorator';
import { BaseService, CoolCache, CoolCommException } from 'midwayjs-cool-core';
import { InjectEntityModel } from '@midwayjs/orm';
import { Repository } from 'typeorm';
import { BaseSysUserEntity } from '../../entity/sys/user';
import { BaseSysPermsService } from './perms';
import * as _ from 'lodash';
import { BaseSysUserRoleEntity } from '../../entity/sys/user_role';
import * as md5 from 'md5';
import { BaseSysDepartmentEntity } from '../../entity/sys/department';

/**
 * 系统用户
 */
@Provide()
export class BaseSysUserService extends BaseService {

    @InjectEntityModel(BaseSysUserEntity)
    baseSysUserEntity: Repository<BaseSysUserEntity>;

    @InjectEntityModel(BaseSysUserRoleEntity)
    baseSysUserRoleEntity: Repository<BaseSysUserRoleEntity>;

    @InjectEntityModel(BaseSysDepartmentEntity)
    baseSysDepartmentEntity: Repository<BaseSysDepartmentEntity>;

    @Inject('cool:cache')
    coolCache: CoolCache;

    @Inject()
    baseSysPermsService: BaseSysPermsService;

    /**
     * 分页查询
     * @param query
     */
    async page(query) {
        const { keyWord, status, departmentIds = [] } = query;
        const permsDepartmentArr = await this.baseSysPermsService.departmentIds(this.ctx.admin.userId); // 部门权限
        const sql = `
        SELECT
            a.id,a.name,a.nickName,a.headImg,a.email,a.remark,a.status,a.createTime,a.updateTime,a.username,a.phone,a.departmentId,
            GROUP_CONCAT(c.name) AS roleName,
            d.name as departmentName
        FROM
            base_sys_user a
            LEFT JOIN base_sys_user_role b ON a.id = b.userId
            LEFT JOIN base_sys_role c ON b.roleId = c.id
            LEFT JOIN base_sys_department d on a.departmentId = d.id
        WHERE 1 = 1
            ${this.setSql(!_.isEmpty(departmentIds), 'and a.departmentId in (?)', [departmentIds])}
            ${this.setSql(status, 'and a.status = ?', [status])}
            ${this.setSql(keyWord, 'and (a.name LIKE ? or a.username LIKE ?)', [`%${keyWord}%`, `%${keyWord}%`])}
            ${this.setSql(true, 'and a.username != ?', ['admin'])}
            ${this.setSql(this.ctx.admin.username !== 'admin', 'and a.departmentId in (?)', [!_.isEmpty(permsDepartmentArr) ? permsDepartmentArr : [null]])}
        GROUP BY a.id
        `;
        return this.sqlRenderPage(sql, query);
    }

    /**
     * 移动部门
     * @param departmentId 
     * @param userIds 
     */
    async move(departmentId, userIds) {
        await this.baseSysUserEntity.createQueryBuilder()
            .update().set({ departmentId })
            .where('id in (:userIds)', { userIds })
            .execute();
    }

    /**
     * 获得个人信息
     */
    async person() {
        const info = await this.baseSysUserEntity.findOne({ id: this.ctx.admin.userId });
        delete info.password;
        return info;
    }

    /**
     * 更新用户角色关系
     * @param user
     */
    async updateUserRole(user) {
        if (user.username === 'admin') {
            throw new CoolCommException('非法操作~');
        }
        await this.baseSysUserRoleEntity.delete({ userId: user.id });
        if (user.roleIdList) {
            for (const roleId of user.roleIdList) {
                await this.baseSysUserRoleEntity.save({ userId: user.id, roleId });
            }
        }
        await this.baseSysPermsService.refreshPerms(user.id);
    }

    /**
     * 新增
     * @param param
     */
    async add(param) {
        const exists = await this.baseSysUserEntity.findOne({ username: param.username });
        if (!_.isEmpty(exists)) {
            throw new CoolCommException('用户名已经存在~');
        }
        param.password = md5('123456'); // 默认密码  建议未改密码不能登陆
        await this.baseSysUserEntity.save(param);
        await this.updateUserRole(param);
        return param.id;
    }

    /**
     * 根据ID获得信息
     * @param id
     */
    public async info (id) {
        const info = await this.baseSysUserEntity.findOne({ id });
        const userRoles = await this.nativeQuery('select a.roleId from base_sys_user_role a where a.userId = ?', [ id ]);
        const department = await this.baseSysDepartmentEntity.findOne({ id: info.departmentId });
        if (info) {
            delete info.password;
            if (userRoles) {
                info.roleIdList = userRoles.map(e => {
                    return parseInt(e.roleId);
                });
            }
        }
        delete info.password;
        if (department) {
            info.departmentName = department.name;
        }
        return info;
    }

     /**
     * 修改个人信息
     * @param param
     */
    public async personUpdate (param) {
        param.id = this.ctx.admin.userId;
        if (!_.isEmpty(param.password)) {
            param.password = md5(param.password);
            const userInfo = await this.baseSysUserEntity.findOne({ id: param.id });
            if (!userInfo) {
                throw new CoolCommException('用户不存在');
            }
            param.passwordV = userInfo.passwordV + 1;
            await this.coolCache.set(`admin:passwordVersion:${param.id}`, param.passwordV);
        } else {
            delete param.password;
        }
        await this.baseSysUserEntity.save(param);
    }

    /**
     * 修改
     * @param param 数据
     */
    async update(param) {
        if (param.id && param.username === 'admin') {
            throw new CoolCommException('非法操作~');
        }
        if (!_.isEmpty(param.password)) {
            param.password = md5(param.password);
            const userInfo = await this.ctx.repo.sys.User.findOne({ id: param.id });
            if (!userInfo) {
                throw new CoolCommException('用户不存在');
            }
            param.passwordV = userInfo.passwordV + 1;
            await this.coolCache.set(`admin:passwordVersion:${param.id}`, param.passwordV);
        } else {
            delete param.password;
        }
        if (param.status === 0) {
            await this.forbidden(param.id);
        }
        await this.baseSysUserEntity.save(param);
        await this.updateUserRole(param);
    }

    /**
     * 禁用用户
     * @param userId
     */
    async forbidden(userId) {
        await this.coolCache.del(`admin:token:${userId}`);
    }


}